package com.jwater.core.manager.proxy;

import com.jwater.core.Bootstrap;
import com.jwater.core.common.JvmNames;
import com.jwater.core.common.S;
import com.jwater.core.manager.common.FileInfoUtils;
import com.jwater.core.manager.common.JvmUtils;
import com.jwater.core.manager.common.ListLogUtils;
import com.jwater.core.manager.common.MsgKeys;
import com.jwater.core.manager.common.conf.CoreConfParse;
import com.jwater.core.manager.common.conf.JobConfParse;
import com.jwater.core.manager.common.deploy.DeployUtils;
import com.jwater.core.manager.common.model.AlarmInfo;
import com.jwater.core.manager.common.model.JobInfo;
import com.jwater.core.manager.common.model.ProxyInfo;
import com.jwater.core.manager.common.model.SystemInfo;
import com.jwater.core.manager.job.JobMain;
import com.jwater.core.manager.proxy.cmd.CmdResult;
import com.jwater.core.manager.proxy.collect.SystemCollect;
import com.jwater.core.net.FileHandler;
import com.jwater.core.net.Node;
import com.jwater.core.net.NodeHandler;
import com.jwater.core.net.SimpleNode;
import com.jwater.core.serialize.ProtoStuffSerialize;
import com.jwater.core.serialize.SerializeUtils;
import com.jwater.core.utils.ProcessUtils;
import com.jwater.core.utils.ProcessUtils.ProcessCallback;
import com.jwater.core.utils.ProcessUtils.ProcessResult;
import com.jwater.launch.HomePath;
import com.jwater.launch.Jwater;
import com.jwater.launch.LoaderUtils;
import jwater.org.apache.commons.io.FileUtils;
import jwater.org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: 代理节点
 * @author: jnner
 * @createDate: 2021/2/5
 * @version: 1.0
 */
public class ProxyNode implements NodeHandler, FileHandler {
    protected static Logger logger = LoggerFactory.getLogger(ProxyNode.class);
    private Node serverNode;
    private CoreConfParse coreConf;
    private String host;
    private Map<String, PrintStream> outFiles = new ConcurrentHashMap<>();
    private AtomicInteger getContentCount = new AtomicInteger(0);
    private Map<Integer, Node> masterNodes = new ConcurrentHashMap<>();
    private SystemCollect systemCollect;
    private ProtoStuffSerialize protoStuffSerialize = new ProtoStuffSerialize();

    /**
     * 启动
     */
    public void start() {
        coreConf = new CoreConfParse();
        coreConf.parse();
        ProxyInfo proxyInfo = coreConf.getLocalProxyInfo();
        if (proxyInfo == null) {
            logger.error("can not get local proxyinfo");
            return;
        }
        this.host = proxyInfo.getHost();
        serverNode = new SimpleNode();
        serverNode.setHandler(this);
        serverNode.setFileHandler(this);
        serverNode.startAsServer(proxyInfo.getPort());
        List<String> allJars = LoaderUtils.getAllJars();
        for (String allJar : allJars) {
            logger.info(allJar);
        }
        logger.info("start proxy success");
        systemCollect = new SystemCollect(this, this.host);
        systemCollect.start();
    }

    public void reportSystemInfo(SystemInfo systemInfo) {
        Node master = getLeaderMaster();
        if (master == null) {
            logger.warn("reportSystemInfo master null");
            return;
        }
        systemInfo.setHost(host);
        logger.info("send reportSystemInfo");
        master.sendData(MsgKeys.PROXY_REPORT, protoStuffSerialize.serialize(systemInfo));
    }

    public void reportAlarmInfo(AlarmInfo alarmInfo) {
        Node master = getLeaderMaster();
        if (master == null) {
            logger.warn("reportAlarmInfo master null");
            return;
        }
        alarmInfo.setHost(host);
        logger.info("send reportAlarmInfo");
        master.sendData(MsgKeys.ALARM_REPORT, protoStuffSerialize.serialize(alarmInfo));
    }

    @Override
    public void onConnect(Node node) {
        logger.info("onConnect:" + node.getNodeId());
    }

    @Override
    public void onDisconnect(Node node) {
        logger.info("onDisconnect:" + node.getNodeId());
        Integer masterId = (Integer) node.getAttribute("masterId");
        if (masterId != null) {
            this.masterNodes.remove(masterId);
        }
    }

    @Override
    public void onData(Node node, String dataType, byte[] data) {
        if ("getFile".equals(dataType)) {
            ProxyExecutorUtils.execute(() -> {
                doForGetFile(node, data);
            });
        } else if ("cmdJvmFile".equals(dataType)) {
            ProxyExecutorUtils.execute(() -> {
                cmdJvmFile(node, data);
            });
        }
    }

    @Override
    public byte[] onSyncCall(Node node, String method, byte[] args) {
        logger.info("onSyncCall:" + method);
        try {
            if ("login".equals(method)) {
                doForLogin(node, args);
            } else if ("startMaster".equals(method)) {
                CmdResult result = doForStartMaster(args);
                return result.serialize();
            } else if ("stopMaster".equals(method)) {
                CmdResult result = doForStopMaster(args);
                return result.serialize();
            } else if ("startProxy".equals(method)) {
                CmdResult result = doForStartProxy(args);
                return result.serialize();
            } else if ("stopProxy".equals(method)) {
                CmdResult result = doForStopProxy(args);
                return result.serialize();
            } else if ("startWorker".equals(method)) {
                CmdResult result = doForStartWorker(args);
                return result.serialize();
            } else if ("stopWorker".equals(method)) {
                CmdResult result = doForStopWorker(args);
                return result.serialize();
            } else if ("cmd".equals(method)) {
                CmdResult result = doForCmd(args);
                return result.serialize();
            } else if ("listFiles".equals(method)) {
                CmdResult result = doForListFiles(args);
                return result.serialize();
            } else if ("preGetFile".equals(method)) {
                CmdResult result = doForPreGetFile(args);
                return result.serialize();
            } else if ("removeFile".equals(method)) {
                CmdResult result = doForRemoveFile(args);
                return result.serialize();
            } else if ("getContent".equals(method)) {
                CmdResult result = doForGetContent(args);
                return result.serialize();
            } else if ("saveContent".equals(method)) {
                CmdResult result = doForSaveContent(args);
                return result.serialize();
            } else if ("deploy".equals(method)) {
                CmdResult result = doForDeploy(args);
                return result.serialize();
            } else if ("removeDeploy".equals(method)) {
                CmdResult result = doForRemoveDeploy(args);
                return result.serialize();
            } else if ("runJob".equals(method)) {
                CmdResult result = doForRunJob(args);
                return result.serialize();
            } else if ("killJob".equals(method)) {
                CmdResult result = doForKillJob(args);
                return result.serialize();
            } else if ("listLogFiles".equals(method)) {
                CmdResult result = listLogFiles(args);
                return result.serialize();
            } else if ("listJvmInfo".equals(method)) {
                CmdResult result = listJvmInfo(args);
                return result.serialize();
            } else if ("cmdJvm".equals(method)) {
                CmdResult result = cmdJvm(args);
                return result.serialize();
            } else if ("listFileInfos".equals(method)) {
                CmdResult result = listFileInfos(args);
                return result.serialize();
            } else if ("changeDeployProp".equals(method)) {
                CmdResult result = changeDeployProp(args);
                return result.serialize();
            }
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
        return new byte[0];
    }

    @Override
    public void onAsyncCall(Node node, String method, byte[] args, ReturnCallback callback) {
        logger.info("onAsyncCall:" + method);
    }

    @Override
    public void onBegin(String category, String fileName) {
        try {
            File dir = new File(HomePath.getTmpFilePath());
            if (!dir.exists()) {
                dir.mkdirs();
            }
            PrintStream ps = new PrintStream(new File(dir, category));
            outFiles.put(category, ps);
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
    }

    @Override
    public void onData(String category, String fileName, int index, byte[] data) {
        try {
            PrintStream ps = outFiles.get(category);
            ps.write(data);
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
    }

    @Override
    public void onEnd(String category, String fileName, int index) {
        try {
            PrintStream ps = outFiles.remove(category);
            ps.close();
            File dest = new File(fileName);
            if (dest.exists()) {
                dest.delete();
            }
            FileUtils.moveFile(new File(HomePath.getTmpFilePath(), category), dest);
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
    }

    @Override
    public void onError(String category, String fileName, String errorMsg) {

    }

    private CmdResult doForStartMaster(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            int index = Integer.parseInt(S.newString(args));
            Bootstrap.startMaster(index, false);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private void doForLogin(Node node, byte[] args) {
        int masterId = Integer.parseInt(S.newString(args));
        node.setAttribute("masterId", masterId);
        masterNodes.put(masterId, node);
    }

    /**
     * 获取leader
     *
     * @return
     */
    private Node getLeaderMaster() {
        Node node = null;
        int min = -1;
        for (Entry<Integer, Node> en : masterNodes.entrySet()) {
            if (node == null || en.getKey() < min) {
                min = en.getKey();
                node = en.getValue();
            }
        }
        return node;
    }

    private CmdResult doForStopMaster(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            int index = Integer.parseInt(S.newString(args));
            Bootstrap.stopMaster(index);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForStartProxy(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Bootstrap.startProxy(false);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForStopProxy(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Bootstrap.stopProxy();
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForStartWorker(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String host = (String) objs[0];
            String regionName = (String) objs[1];
            String deployName = (String) objs[2];
            String groupName = (String) objs[3];
            String workerName = (String) objs[4];
            int index = (int) objs[5];
            String jvmArgs = (String) objs[6];
            Map<String, String> envs = DeployUtils.getWorkerEnvs(regionName, deployName, groupName, workerName);
            Bootstrap.runWorker(host, regionName, deployName, groupName, workerName, index, jvmArgs, false, (map) -> {
                // 获取worker配置文件，解析是否有环境变量，有的话设置环境变量
                for (Entry<String, String> en : envs.entrySet()) {
                    map.put(en.getKey(), en.getValue());
                }
            });
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForStopWorker(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String regionName = (String) objs[0];
            String deployName = (String) objs[1];
            String groupName = (String) objs[2];
            String workerName = (String) objs[3];
            int index = (int) objs[4];
            boolean isForce = (boolean) objs[5];
            Bootstrap.killWorker(regionName, deployName, groupName, workerName, index, isForce);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForCmd(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            String cmd = S.newString(args);
            List<String> lines = ProcessUtils.cmd(null, cmd);
            result.setSuccess(true);
            result.setData(lines);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForListFiles(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String dstDir = (String) objs[0];
            boolean recursive = (boolean) objs[1];
            List<String> list = new ArrayList<String>();
            File dir = new File(dstDir);
            if (dir.exists()) {
                listFiles(list, dir, recursive);
            }
            result.setSuccess(true);
            result.setData(list);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private void listFiles(List<String> list, File dir, boolean recursive) {
        File[] files = dir.listFiles();
        if (files == null) {
            return;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                if (recursive) {
                    listFiles(list, file, recursive);
                }
            } else {
                list.add(file.getPath());
            }
        }
    }

    private CmdResult doForPreGetFile(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            File dst = new File(S.newString(args));
            if (dst.exists()) {
                result.setSuccess(true);
            } else {
                result.setSuccess(false);
                result.setMsg("file not exist:" + dst);
            }
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private void doForGetFile(Node node, byte[] data) {
        Object[] objs = SerializeUtils.deserializeArray(data);
        String dst = (String) objs[0];
        String category = (String) objs[1];
        String fileName = (String) objs[2];
        try {
            FileInputStream fis = new FileInputStream(new File(dst));
            node.sendFile(category, fileName, fis);
            fis.close();
        } catch (Exception e) {
            logger.error(e.toString(), e);
            node.sendFileError(category, fileName, e.toString());
        }
    }

    private CmdResult doForRemoveFile(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            File dst = new File(S.newString(args));
            boolean success = true;
            if (dst.exists()) {
                success = FileUtils.deleteQuietly(dst);
            }
            result.setSuccess(success);
            if (!success) {
                result.setMsg("删除文件失败" + dst);
            }
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForGetContent(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            int count = getContentCount.incrementAndGet();
            if (count > 5) {
                result.setSuccess(false);
                result.setMsg("many request for getContent");
                return result;
            }
            Object[] objs = SerializeUtils.deserializeArray(args);
            String dst = (String) objs[0];
            int lineLimit = (int) objs[1];
            int lineLenLimit = (int) objs[2];

            File dstFile = new File(dst);
            if (!dstFile.exists()) {
                result.setSuccess(false);
                result.setMsg("file not exist:" + dst);
                return result;
            }

            if (lineLimit == -1) {
                FileInputStream fis = new FileInputStream(dstFile);
                String content = IOUtils.toString(fis);
                fis.close();
                result.setSuccess(true);
                result.setData(content);
            } else {
                FileInputStream fis = new FileInputStream(dstFile);
                BufferedReader br = new BufferedReader(new InputStreamReader(fis, S.charset));
                String line = null;
                LinkedList<String> lines = new LinkedList<String>();
                while ((line = br.readLine()) != null) {
                    if (line.length() > lineLenLimit) {
                        line = line.substring(0, lineLenLimit);
                    }
                    lines.add(line);
                    if (lines.size() > lineLimit) {
                        lines.removeFirst();
                    }
                }
                br.close();
                StringBuilder sb = new StringBuilder();
                for (String l : lines) {
                    sb.append(l).append("\r\n");
                }
                result.setSuccess(true);
                result.setData(sb.toString());
            }
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        } finally {
            getContentCount.decrementAndGet();
        }
        return result;
    }

    private CmdResult doForSaveContent(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String dst = (String) objs[0];
            String content = (String) objs[1];
            FileUtils.write(new File(dst), content, S.charset);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForDeploy(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String fileName = (String) objs[0];
            String dst = (String) objs[1];
            String regionName = (String) objs[2];
            String deployName = (String) objs[3];
            String keepConf = (String) objs[4];
            long version = (long) objs[5];
            String path = (String) objs[6];
            DeployUtils.deploy(fileName, dst, regionName, deployName, keepConf, version, path);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForRemoveDeploy(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String regionName = (String) objs[0];
            String deployName = (String) objs[1];
            DeployUtils.removeDeploy(regionName, deployName);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult doForRunJob(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String regionName = (String) objs[0];
            String deployName = (String) objs[1];
            String groupName = (String) objs[2];
            String jobName = (String) objs[3];
            long time = (long) objs[4];
            boolean once = (boolean) objs[5];
            JobConfParse jobConf = new JobConfParse();
            jobConf.parseDeploy(regionName, deployName);
            JobInfo jobInfo = jobConf.getJobInfo(regionName, deployName, groupName, jobName);
            if (jobInfo == null) {
                result.setSuccess(false);
                result.setMsg("can not find job conf:" + groupName + ":" + jobName);
            } else {
                RunJob runJob = new RunJob();
                runJob.jobInfo = jobInfo;
                runJob.time = time;
                runJob.once = once;
                new Thread(runJob).start();
                result.setSuccess(true);
            }
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    public class RunJob implements Runnable, ProcessCallback {
        private JobInfo jobInfo;
        private long time;
        private boolean once;
        private boolean isAlive = true;

        @Override
        public void onMsg(String msg) {
        }

        @Override
        public void onErrorMsg(String msg) {
        }

        @Override
        public void onStop() {
            isAlive = false;
        }

        @Override
        public void run() {
            try {
                String jvmArgs = jobInfo.getProps().getString("jvm", "-Xms128m -Xmx1g");
                List<String> extLibDirs = new ArrayList<String>();
                extLibDirs.add(HomePath.getLaunch());
                String regionName = jobInfo.getRegionName();
                String deployName = jobInfo.getDeployName();
                String groupName = jobInfo.getGroupName();
                String jobName = jobInfo.getJobName();
                String args = JobMain.class.getName() + " " + regionName + " " + deployName + " " + groupName + " "
                        + jobName + " " + time + " "
                        + JvmNames.getJobName(coreConf.getClusterName(), regionName, deployName, groupName, jobName);
                ProcessResult processResult = ProcessUtils.exeClazzName(Jwater.class.getName(), jvmArgs, extLibDirs,
                        args, this);
                long blockTime = jobInfo.getProps().getLong("blockTime", 1800l) * 1000;
                long waitTime = 0;
                while (isAlive) {
                    TimeUnit.MILLISECONDS.sleep(100);
                    waitTime += 100;
                    if (waitTime > blockTime) {
                        break;
                    }
                }
                processResult.process.destroy();
                if (!once) {
                    Node node = getLeaderMaster();
                    if (node == null || !node.isConnect()) {
                        logger.error(
                                "can not send job complete msg,master not online,for:" + groupName + ":" + jobName);
                        logger.info(node.getNodeId() + ",masterId:" + node.getAttribute("masterId"));
                        return;
                    }
                    byte[] bytes = SerializeUtils.serializeArray(regionName, deployName, groupName, jobName, time);
                    node.syncCall("completeJob", bytes);
                }
            } catch (Exception e) {
                logger.error(e.toString(), e);
            }
        }
    }

    private CmdResult doForKillJob(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String regionName = (String) objs[0];
            String deployName = (String) objs[1];
            String groupName = (String) objs[2];
            String jobName = (String) objs[3];
            Bootstrap.killJob(regionName, deployName, groupName, jobName);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult listLogFiles(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String regionName = (String) objs[0];
            String dir = (String) objs[1];
            result.setData(ListLogUtils.listLog(regionName, dir));
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult listJvmInfo(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            result.setData(JvmUtils.listJvm());
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult cmdJvm(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String cmdType = (String) objs[0];
            int pid = (int) objs[1];
            String dst = JvmUtils.cmdJvm(cmdType, pid);
            if (dst != null) {
                result.setData(dst);
                result.setSuccess(true);
            } else {
                result.setSuccess(false);
                result.setMsg("cmd jvm fail");
            }
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult cmdJvmFile(Node node, byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String dst = (String) objs[0];
            String category = (String) objs[1];
            String fileName = (String) objs[2];
            File tempFile = new File(dst);
            FileInputStream fis = new FileInputStream(tempFile);
            node.sendFile(category, fileName, fis);
            fis.close();
            result.setSuccess(true);
            tempFile.delete();
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult listFileInfos(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            String dstDir = S.newString(args);
            result.setData(FileInfoUtils.listFileInfos(dstDir));
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }

    private CmdResult changeDeployProp(byte[] args) {
        CmdResult result = new CmdResult();
        try {
            Object[] objs = SerializeUtils.deserializeArray(args);
            String regionName = (String) objs[0];
            String deployName = (String) objs[1];
            String key = (String) objs[2];
            String value = (String) objs[3];
            DeployUtils.updateInfoProp(regionName, deployName, key, value);
            result.setSuccess(true);
        } catch (Exception e) {
            logger.error(e.toString(), e);
            result.setSuccess(false);
            result.setMsg(e.toString());
        }
        return result;
    }
}
